class_name  Board
extends Node

@export var tetromino_scens : PackedScene

#@onready var panel_container: PanelContainer = $"../PanelContainer"

signal  tetromino_locked
signal  game_over

var tetrominos:Array[Tetromino] = []
var next_tetromino

var clear_line_info

const ROW_COUNT = 20
const COLLUMN_COUNT = 10


#在棋盘节点中，棋盘需要执行具体的方块的实例化的操作，但具体实力化什么方块，在哪里，不需要在这里管理
func spawn_tetromino(type :Shared.Tetromino ,is_next_piece,spawn_pos):
	#
	#使用字典来索引获取到的资源类，方便后续实例化设置好的方块颜色
	var tetromino_data = Shared.data[type]
	var tetromino = tetromino_scens .instantiate() as Tetromino
	
	#设置传入的参数
	tetromino.tetromino_data = tetromino_data
	tetromino.is_next_piece = is_next_piece
	
	#如果是当前块，那么将这个方块的位置设置为资源类设置好的属性值设置好给到生成的对象
	if is_next_piece == false :
		#设置生成位置
		tetromino.position = tetromino_data.spawn_pos
		#把当前生成的方块加入一个集合
		tetromino.other_tetromino = tetrominos
		#链接停滞信号
		tetromino.lock_tetromino.connect(on_tetromino_lock)
		#将该块添加为Board的子节点
		add_child(tetromino)
	#else :
		#tetromino.scale = Vector2(0.5,0.5)
		##_add_tetromino_to_container(tetromino)
		#tetromino.set_position(spawn_pos)
		#next_tetromino = tetromino


func  on_tetromino_lock(tetromino:Tetromino):
#	next_tetromino.queue_free()
	tetrominos.append(tetromino)
	tetromino_locked.emit()
	#每当一个方块被锁定后，就检查是否结束游戏已经是否可以触发消除
	check_game_over()
	clear_lines()

func check_game_over():
	for tetromino in tetrominos:
		var pieces = tetromino.get_children().filter(func (c): return c as Piece)
		for piece in pieces:
			var y_loc = piece.global_position.y
			if y_loc == -456:
				game_over.emit()

func clear_lines():
	var board_pieces = fill_board_pieces()
	clear_board_pieces(board_pieces)

func fill_board_pieces():
	var board_pieces = []
	
	for i in ROW_COUNT:
		board_pieces.append([])
		
	for cube in tetrominos:
		var tetromino_pieces = cube.get_children().filter(func(c):return c is Piece)
		for piece in tetromino_pieces:
			
			var row  = (piece.global_position.y + piece.get_size().y/ 2 ) / piece.get_size().y + ROW_COUNT/2
			row = int(row)
			board_pieces[row - 1].append(piece)
			
	return board_pieces
	
func clear_board_pieces(board_pieces):
	var rows_to_clear = []
	
	# Step 1: 先找到所有需要清除的行
	var i = ROW_COUNT
	while i > 0:
		var row_to_analyze = board_pieces[i-1]
		
		if row_to_analyze.size() == COLLUMN_COUNT:
			rows_to_clear.append(i-1)  # 记录需要清除的行的索引
		i -= 1
	
	var row = rows_to_clear.size()

	print("当前需要删除的数量为  %d " % [row * COLLUMN_COUNT])
	#row * COLLUMN_COUNT即当前所需要转移到下落位置的方块数量
	#为了尝试保证扩展性，并且需要重新指定父节点为刚体，有如下两种设想方案
	#1.直接传递当前要被删除的方块对象，但是需要重新指定父节点为刚体（尚未尝试）
	#2.利用一个数组存储当前被删除对象的纹理图片，然后赋值纹理后根据转移数量 * 行数奖励 生成更多的方块（尚未尝试）
	
	# Step 2: 清除所有标记的行
	for row_index in rows_to_clear:
		clear_row(board_pieces[row_index])  # 清除行内的方块
		board_pieces[row_index].clear()     # 清空这一行在 board_pieces 中的记录

	# Step 3: 统一移动所有方块
	move_all_row_pieces_down(board_pieces, rows_to_clear)

func move_all_row_pieces_down(board_pieces, rows_to_clear):
	# 计算每一行应该下移的距离
	for row_index in range(ROW_COUNT - 1, -1, -1):  # 从最顶端行开始
		var row_to_move = board_pieces[row_index]
		
		if row_to_move.size() == 0:
			continue  # 如果当前行没有方块，跳过

		# 计算这行应该下移的次数：它上方被清除的行数
		var drop_count = 0
		for clear_row_index in rows_to_clear:
			if row_index < clear_row_index:
				drop_count += 1

		# 如果有需要移动的行
		if drop_count > 0:
			for piece in row_to_move:
				piece.position.y += piece.get_size().y * drop_count  # 根据清除的行数移动

			# 将当前行的方块移动到新的行
			board_pieces[row_index + drop_count].append_array(row_to_move)
			board_pieces[row_index].clear()


func clear_row (row):
	for piece in row:
		piece.queue_free()
